/*
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is ST_EXT-S_UIMAST.
 *
 * The Initial Developer of the Original Code is
 * University of Rome, Tor Vergata
 * Portions created by the Initial Developer are Copyright (C) 2009
 * the Initial Developer. All Rights Reserved.
 */

package it.uniroma2.art.uimast.impl;

import it.uniroma2.art.ontapi.ARTResource;
import it.uniroma2.art.uimast.xpts.Variant;

import java.util.*;
import org.apache.uima.cas.*;
import org.w3c.dom.Element;

/**
 * Assigns several values to an array-valued feature.
 * 
 * @author <a href="mailto:manuel.fiorelli@gmail.com">Manuel Fiorelli</a>
 */
public class ArrayValuedFeature extends MultiValuedFeature
{

	/**
	 * Constructs an <code>ArrayValued</code> object.
	 * @param classProjection the owner class projection
	 * @param feature the feature to initialize
	 * @param e the DOM element describing this projection
	 * @throws Exception
	 */
    public ArrayValuedFeature(ClassProjection classProjection, Feature feature, Element e)
        throws Exception
    {
        super(classProjection, feature, feature.getRange().getComponentType(), DataSource.create(classProjection, classProjection.getCAS().getTypeSystem(), feature.getRange().getComponentType(), e));
    }

    /**
     * Constructs an <code>ArrayValued</code> object.
     * @param classProjection the owner class projection 
     * @param feature the feature to initialize
     * @param mode the projection mode: either <code>value</code> or <code>property</code>
     * @param value the value lexical representation or the property URI
     * @throws Exception
     */
    public ArrayValuedFeature(ClassProjection classProjection, Feature feature, String mode, String value)
        throws Exception
    {
        super(classProjection, feature, feature.getRange().getComponentType(), DataSource.create(classProjection, classProjection.getCAS().getTypeSystem(), feature.getRange(), mode, value));
    }

    @Override
    public void apply(ARTResource domainObject, ARTResource annot, FeatureStructure fs)
    {
        Iterator<Variant> it = dataSource.apply(domainObject, annot);
        List<String> values = new LinkedList<String>();
       
        while(it.hasNext()) {
        	values.add(it.next().getValueAsString());
        }
        
        CommonArrayFS array = createArray(componentType, values.size());
        array.copyFromArray(values.toArray(new String[0]), 0, 0, values.size());
        
        fs.setFeatureValue(feature, array);
    }

    /**
     * Creates an array.
     * @param componentType the array component type
     * @param size the array size
     * @return an array
     */
    private CommonArrayFS createArray(Type componentType, int size)
    {
    	CAS cas = classProjection.getCAS();
    	
        String name = componentType.getName();
        if(name.equals("uima.cas.String"))
            return cas.createStringArrayFS(size);
        if(name.equals("uima.cas.Boolean"))
            return cas.createBooleanArrayFS(size);
        if(name.equals("uima.cas.Byte"))
            return cas.createByteArrayFS(size);
        if(name.equals("uima.cas.Short"))
            return cas.createArrayFS(size);
        if(name.equals("uima.cas.Integer"))
            return cas.createIntArrayFS(size);
        if(name.equals("uima.cas.Long"))
            return cas.createLongArrayFS(size);
        if(name.equals("uima.cas.Float"))
            return cas.createFloatArrayFS(size);
        if(name.equals("uima.cas.Double"))
            return cas.createDoubleArrayFS(size);
        else
            return cas.createArrayFS(size);
    }
}
